//
// 如果是基于riot的单页面应用可以pip.load此文件
// @required bootstrap/riot.js
//

;(function(window, undefined) {

  var RiotApp = function(options){
    if(RiotApp.instance) return RiotApp.instance;
    if(!'pip' in window) throw new Error('需要pip库');
    if(!'riot' in window) throw new Error('需要riot库');
    pip.emitter(this);
    this.opts = pip.assign({
      id: 'app',
      lang: 'cn',
      style: 'default', // 样式名称
      mount: '#app', // tag 挂载位置
      version: '1.0',
      json: './static/app.json', // app json 数据地址
      debug: true,
      preload: null // 预加载资源
    }, options);
    this.init();
    RiotApp.instance = this;
    return RiotApp.instance;
  }

  /**
   * 初始化操作
   */
  RiotApp.prototype.init = function(){

    var _this = this, opts = this.opts;

    _this.on('init::route', function(args){

      _this.log('路由:', args);

      var
        name = args[0] || 'index',
        file = _this.data.tags[name],
        tag = opts.id+'-'+name;

      if(!file){
        if(_this.data.tags['404']){
          window.location.replace('#!404');
        }
        else{
          alert('页面'+name+'不存在');
          history.back();
        }
        _this.log('数据中没有找到tag:', name);
        return;
      }

      _this.url = '';
      _this.path = [];
      _this.query = {};
      _this.search = function(q){
        return _this.url+'?'
        +pip.serialize(pip.assign(_this.query, q || {}));
      };

      for(var i in args){
        if(pip.typeOf(args[i]) === 'Object'){
          _this.query = args[i];
        }
        else if(pip.typeOf(args[i]) === 'String'){
          _this.path.push(args[i]);
          _this.url += (args[i] + '/');
        }
      }
      _this.url = _this.url.slice(0, -1);

      pip.load(file).on('done', function(){
        try{
          riot.mixin({ app: _this });
          riot.mount(opts.mount, tag);
          _this.log('mount tag:', tag);
        } catch(e) {
          if(_this.data.tags['500']){
            window.location.replace('#!500');
          }
          else{
            alert('页面'+name+'出错');
            history.back();
          }
          _this.log(e);
        }
      }).on('error', function(file){
        throw new Error('tag文件地址错误: '+file);
      });

    });
    // 设置路由
    if(window.route){
      route.base('#!');
      route.parser(function(path){
        var raw = path.split('?'),
          uri = raw[0].split('/'),
          qs = raw[1];
        if (qs) uri.push(pip.search2obj(qs));
        return uri;
      });
      route(function(){
        _this.emit('init::route', arguments);
      });
      _this.once('init::data', function(){
        _this.log('JSON数据:', _this.data);
        route.start(true);
      });
    }

    // 加载json数据 -> app.data
    pip.xhr(opts.json+'?v='+opts.version, {
      cache: !opts.debug
    })
    .on('done', function(data){

      var preload = 0;
      _this.data = data;
      _this.data.lang = data[opts.lang] || {};

      // 预加载操作完毕后发送初始化完毕
      _this.on('init::preload', function(){
        preload++;
        if(preload === 2){
          _this.emit('init::data');
        }
      })

      if(_this.data.styles[opts.style]){
        // 载入样式
        pip.load(_this.data.styles[opts.style])
        .on('done', function(){
          _this.log('样式:', opts.style);
          _this.emit('init::preload');
        });
      } else {
        _this.emit('init::preload');
      }

      if(pip.typeOf(opts.preload) === 'Function'){
        // 预加载
        opts.preload.apply(_this)
        .on('done', function(files){
          _this.log('预加载资源:', files);
          _this.emit('init::preload');
        });
      } else {
        _this.emit('init::preload');
      }

    })
    .on('error', function(status){
      _this.log('数据地址获取失败:', opts.json);
    });

  };

  /**
   * 在非debug下显示
   * @return {Mixed} 消息
   */
  RiotApp.prototype.log = function(){
    if(!this.opts.debug) return;
    window.console &&
    window.console.log.apply(null, arguments);
  }

  if (typeof exports === 'object')
    module.exports = RiotApp
  else if (typeof define === 'function' && define.amd)
    define(function() { return RiotApp })
  else
    window.RiotApp = RiotApp

})(typeof window != 'undefined' ? window : undefined);
